#include "gtest/gtest.h"
#include "DataStructure/Common/Constant.h"
#include "../../IntegrationFormula/Gauss2D3X3P.h"
#include "../Quad9NodeShpFunc.h"

using SG::DataStructure::Common::TOLERANCE;
using SG::Algebra::Matrixd;
using SG::FEMSolver::Element::Quad9NodeShpFunc;
using SG::DataStructure::FEM::IntegPointArray; 

// 测试: 形函数应在本点为1，它点为0
TEST(Quad9NodeShpFuncTest, shpFuncKroneckerDeltaTest) {

    // 定义节点的坐标
    IntegPointArray nodes(9);  // 9节点数组（用IntegPoint存储(x,y)）
    nodes[0].m_x = -1.0; nodes[0].m_y = -1.0;  // 节点0：左下角
    nodes[1].m_x =  1.0; nodes[1].m_y = -1.0;  // 节点1：右下角
    nodes[2].m_x =  1.0; nodes[2].m_y =  1.0;  // 节点2：右上角
    nodes[3].m_x = -1.0; nodes[3].m_y =  1.0;  // 节点3：左上角
    nodes[4].m_x =  0.0; nodes[4].m_y = -1.0;  // 节点4：下边缘中点
    nodes[5].m_x =  1.0; nodes[5].m_y =  0.0;  // 节点5：右边缘中点
    nodes[6].m_x =  0.0; nodes[6].m_y =  1.0;  // 节点6：上边缘中点
    nodes[7].m_x = -1.0; nodes[7].m_y =  0.0;  // 节点7：左边缘中点
    nodes[8].m_x =  0.0; nodes[8].m_y =  0.0;  // 节点8：中心节点（9节点新增）

    // 创建形函数对象并计算9个节点处的形函数值
    Quad9NodeShpFunc shpFunc;
    shpFunc.Compute(nodes);  

    // 验证
    auto& shp0 = shpFunc.GetShapeFunction(0);
    Matrixd target0(1, 9);  // 9行1列矩阵（9个形函数值）
    target0(0, 0) = 1.0;
    ASSERT_TRUE(shp0 == target0) ;

    auto& shp1 = shpFunc.GetShapeFunction(1);
    Matrixd target1(1, 9);
    target1(0, 1) = 1.0;
    ASSERT_TRUE(shp1 == target1);

    auto& shp2 = shpFunc.GetShapeFunction(2);
    Matrixd target2(1, 9);  // 修正为1行9列行矩阵：列对应9个节点的形函数值
    target2(0, 2) = 1.0;    // 第0行第2列：节点2的形函数值设为1
    ASSERT_TRUE(shp2 == target2) << "节点2处形函数性质验证失败";

    auto& shp3 = shpFunc.GetShapeFunction(3);
    Matrixd target3(1, 9);
    target3(0, 3) = 1.0;    // 第0行第3列：节点3的形函数值设为1
    ASSERT_TRUE(shp3 == target3) << "节点3处形函数性质验证失败";

    auto& shp4 = shpFunc.GetShapeFunction(4);
    Matrixd target4(1, 9);
    target4(0, 4) = 1.0;    // 第0行第4列：节点4的形函数值设为1
    ASSERT_TRUE(shp4 == target4) << "节点4处形函数性质验证失败";

    auto& shp5 = shpFunc.GetShapeFunction(5);
    Matrixd target5(1, 9);
    target5(0, 5) = 1.0;    // 第0行第5列：节点5的形函数值设为1
    ASSERT_TRUE(shp5 == target5) << "节点5处形函数性质验证失败";

    auto& shp6 = shpFunc.GetShapeFunction(6);
    Matrixd target6(1, 9);
    target6(0, 6) = 1.0;    // 第0行第6列：节点6的形函数值设为1
    ASSERT_TRUE(shp6 == target6) << "节点6处形函数性质验证失败";

    auto& shp7 = shpFunc.GetShapeFunction(7);
    Matrixd target7(1, 9);
    target7(0, 7) = 1.0;    // 第0行第7列：节点7的形函数值设为1
    ASSERT_TRUE(shp7 == target7) << "节点7处形函数性质验证失败";

    auto& shp8 = shpFunc.GetShapeFunction(8);
    Matrixd target8(1, 9);
    target8(0, 8) = 1.0;    // 第0行第8列：节点8的形函数值设为1
    ASSERT_TRUE(shp8 == target8) << "中心节点8处形函数性质验证失败";
}

// 验证雅各比矩阵，jocobian为单位矩阵
TEST (Quad9NodeShpFuncTest, shpFuncDerivativeTest)
{
    // Input
    SG::FEMSolver::Element::Gauss2D3X3P integCalc;
    auto integs = integCalc.GetPoints ();
    Matrixd nodes (9, 2);

    nodes (0, 0) = -1.0; nodes (0, 1) = -1.0;
    nodes (1, 0) =  1.0; nodes (1, 1) = -1.0;
    nodes (2, 0) =  1.0; nodes (2, 1) =  1.0;
    nodes (3, 0) = -1.0; nodes (3, 1) =  1.0;
    nodes (4, 0) =  0.0; nodes (4, 1) = -1.0;
    nodes (5, 0) =  1.0; nodes (5, 1) =  0.0;
    nodes (6, 0) =  0.0; nodes (6, 1) =  1.0;
    nodes (7, 0) = -1.0; nodes (7, 1) =  0.0;
    nodes (8, 0) =  0.0; nodes (8, 1) =  0.0;

    // Target data
    auto I = SG::Algebra::identity (2);

    // Test data
    auto shpfunc = Quad9NodeShpFunc ();
    shpfunc.Compute (integs);

    // 测试9个积分点形函数导数
    for (std::size_t index = 0; index < 9; ++index)
    {
        auto I1 = shpfunc.GetShapeFunctionDerivative (index) * nodes;        
        ASSERT_TRUE (I1 == I);
    }
}
